home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Chans / 822-local / code.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  8.7 KB  |  564 lines

  1. /* code.c: interpreter code */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/822-local/RCS/code.c,v 6.0 1991/12/18 20:04:31 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Chans/822-local/RCS/code.c,v 6.0 1991/12/18 20:04:31 jpo Rel $
  9.  *
  10.  * $Log: code.c,v $
  11.  * Revision 6.0  1991/12/18  20:04:31  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15.  
  16.  
  17.  
  18. /* This stuff based heavily on Kernigan & Pike's hoc */
  19.  
  20. #include "util.h"
  21. #include "loc.h"
  22. #include "retcode.h"
  23. #include "expand.h"
  24. #include <isode/cmd_srch.h>
  25.  
  26. #ifndef NULLCP
  27. #define NULLCP ((char *)0)
  28. #endif
  29. #define NSTACK    1024
  30. static Datum    stack[NSTACK];
  31. static Datum    *stackp;
  32.  
  33. #define NPROG    2000
  34. Inst    prog[NPROG];
  35. Inst    *progp, *pc;
  36.  
  37. static char true[] = "true", false[] = "", rp_agn[] = "again",
  38.     delivered[] = "delivered", permfail[] = "perm";
  39. #define istrue(x)    (*x)
  40.  
  41. int     lineno;
  42. int    debug = 0;
  43.  
  44. static struct {
  45.     char    *name;
  46.     char    *val;
  47. } consts[] = {
  48.     "TRUE",        true,
  49.     "FALSE",    false,
  50.     "OK",        true,
  51.     "PERMFAIL",    permfail,
  52.     "TEMPFAIL",    rp_agn,
  53.     0,        0
  54. };
  55.  
  56. static CMD_TABLE tbl_codes[] = {
  57.     true,        RP_OK,
  58.     rp_agn,        RP_AGN,
  59.     false,        RP_NOOP,
  60.     permfail,    RP_BAD,
  61.     0,        -1
  62. };
  63.  
  64. static int exiting;
  65. extern char *strdup ();
  66.  
  67. initialise ()
  68. {
  69.     Symbol    *sp;
  70.     int    i;
  71.  
  72.     stackp = stack;
  73.     progp = prog;
  74.     if (!lookup (delivered)) {
  75.         sp = install (delivered, strvar);
  76.         sp -> str = false;
  77.         for (i = 0; consts[i].name; i++) {
  78.             sp = install (consts[i].name, constant);
  79.             sp -> str = consts[i].val;
  80.         }
  81.     }
  82.     exiting = 0;
  83. }
  84.  
  85. #ifdef DISASS
  86. static CMD_TABLE procs[] = {
  87.     "ifcode",    (int) ifcode,
  88.     "eq",        (int) eq,
  89.     "ne",        (int) ne,
  90.     "or",        (int) or,
  91.     "and",        (int) and,
  92.     "stringpush",    (int) stringpush,
  93.     "tofile",    (int) tofile,
  94.     "topipe",    (int) topipe,
  95.     "exitproc",    (int) exitproc,
  96.     "varpush",    (int) varpush,
  97.     "setdeliver",    (int) setdeliver,
  98.     "eval",        (int) eval,
  99.     "defexitproc",    (int) defexitproc,
  100.     "not",        (int) not,
  101.     "unixmail",    (int) tounixfile,
  102.     "STOP",        0,
  103.     0,        -1
  104. };
  105. #endif
  106.  
  107. run ()
  108. {
  109.     Symbol    *sp;
  110.     int    retval;
  111. #ifdef DISASS
  112.     Inst    *p;
  113.     char    *cp;
  114.  
  115.     for (p = prog; p < progp; p++)
  116.         if (cp = rcmd_srch (*p, procs))
  117.             PP_TRACE (("%d %s", p - prog, cp));
  118.         else
  119.             PP_TRACE (("%d %x", p - prog, *p));
  120.  
  121. #endif
  122.     execute (prog);
  123.  
  124.     sp = lookup (delivered);
  125.     if (sp == NULL)
  126.         adios (NULLCP, "symbol %s not defined!!", delivered);
  127.     switch (retval = cmd_srch (sp -> str, tbl_codes)) {
  128.         case RP_AGN:
  129.         case RP_BAD:
  130.         case RP_OK:
  131.         case RP_NOOP:
  132.         break;
  133.  
  134.         default:
  135.         adios (NULLCP, "Unknown return state '%s'", sp -> str);
  136.     }
  137.     return retval;
  138. }
  139.  
  140. execute (p)
  141. Inst    *p;
  142. {
  143.     Inst tmppc;
  144.  
  145.     for (pc = p; *pc != STOP && !exiting; ) {
  146.         tmppc = *pc ++;    /* work around ultrix bug */
  147.         (*tmppc) ();
  148.     }
  149. }
  150.  
  151. Datum    pop ()
  152. {
  153.     if (stackp == stack)
  154.         adios (NULLCP, "stack underflow");
  155.     return *--stackp;
  156. }
  157.  
  158. push (d)
  159. Datum    d;
  160. {
  161.     if (stackp >= &stack[NSTACK])
  162.         adios (NULLCP, "stack overflow");
  163.     *stackp++ = d;
  164. }
  165.  
  166. Inst    *code (f)
  167. Inst    f;
  168. {
  169.     Inst    *oprogp = progp;
  170.  
  171.     if (progp >= &prog[NPROG])
  172.         adios (NULLCP, "program too big");
  173.     *progp++ = f;
  174.     return oprogp;
  175. }
  176.  
  177. void or ()
  178. {
  179.     Datum d1, d2;
  180.  
  181.     d1 = pop ();
  182.     d2 = pop ();
  183.     PP_TRACE (("%s or %s", d1.str, d2.str));
  184.     d1.str = (istrue(d1.str) || istrue(d2.str) ? true : false);
  185.     push (d1);
  186. }
  187.  
  188. void and ()
  189. {
  190.     Datum d1, d2;
  191.  
  192.     d1 = pop ();
  193.     d2 = pop ();
  194.     PP_TRACE (("%s and %s", d1.str, d2.str));
  195.     d1.str = (istrue(d1.str) && istrue(d2.str) ? true : false);
  196.     push (d1);
  197. }
  198.         
  199.  
  200. void eq ()
  201. {
  202.     Datum d1, d2;
  203.  
  204.     d2 = pop ();
  205.     d1 = pop ();
  206.     PP_TRACE (("%s eq %s", d1.str, d2.str));
  207.     d1.str = (lexequ (d1.str, d2.str) == 0 ? true : false);
  208.     push (d1);
  209. }
  210.  
  211. void    ne ()
  212. {
  213.     PP_TRACE (("not (psuedo)"));
  214.     eq ();
  215.     not ();
  216. }
  217.  
  218. void    req ()
  219. {
  220.     Datum d1, d2;
  221.     char    *cp, *dp, *re_comp ();
  222.     static char *rbuf;
  223.     static int rbsize;
  224.     int s;
  225.  
  226.     d2 = pop ();
  227.     d1 = pop ();
  228.  
  229.     PP_TRACE (("%s req %s", d1.str, d2.str));
  230.     if (cp = re_comp (d2.str))
  231.         adios (NULLCP, "Bad re expression %s: %s", d2.str, cp);
  232.     s = strlen (d1.str);
  233.     if (rbuf == NULLCP)
  234.         rbuf = malloc ((unsigned)(rbsize = (s + 1)));
  235.     else if (s + 1 > rbsize)
  236.         rbuf = realloc (rbuf, (unsigned) (rbsize = s + 1));
  237.     for (cp = d1.str, dp = rbuf; *cp; cp ++) {
  238.         if (isascii (*cp) && isupper (*cp))
  239.             *dp++ = tolower (*cp);
  240.         else *dp ++ = *cp;
  241.     }
  242.     *dp = '\0';
  243.  
  244.     if (re_exec (rbuf))
  245.         d1.str = true;
  246.     else    d1.str = false;
  247.     push (d1);
  248. }
  249.  
  250. void not ()
  251. {
  252.     Datum d;
  253.  
  254.     d = pop ();
  255.     PP_TRACE (("not %s", d.str));
  256.     d.str = istrue(d.str) ? false : true;
  257.     push (d);
  258. }
  259.  
  260. void    eval ()
  261. {
  262.     Datum    d;
  263.  
  264.     d = pop ();
  265.  
  266.     PP_TRACE (("eval %s", d.sym -> str ? d.sym -> str :
  267.          "<empty>"));
  268.     if (d.sym -> str == (char *)0)
  269.         d.str = false;
  270.     else    d.str = d.sym -> str;
  271.     push(d);
  272. }
  273.  
  274. void stringpush ()
  275. {
  276.     Datum    d;
  277.  
  278.     d.str = (char *)*pc ++;
  279.     PP_TRACE (("stringpush %s", d.str));
  280.     push (d);
  281. }
  282.  
  283. void varpush ()
  284. {
  285.     Datum    d;
  286.  
  287.     d.sym = (Symbol *)(*pc ++);
  288.     PP_TRACE (("varpush %s", d.sym -> str));
  289.     push (d);
  290. }
  291.  
  292. void    ifcode ()
  293. {
  294.     Datum    d;
  295.     Inst    *savepc = pc;
  296.  
  297.     PP_TRACE (("ifcode"));
  298.     execute (savepc+3);    /* then part */
  299.  
  300.     d = pop ();
  301.     if (istrue(d.str)) {
  302.         PP_TRACE (("then code"));
  303.         execute (*((Inst **)(savepc)));
  304.     }
  305.     else if (*((Inst **)(savepc+1))) { /* else part */
  306.         PP_TRACE (("else code"));
  307.         execute (*((Inst **)(savepc + 1)));
  308.     }
  309.     PP_TRACE (("endif"));
  310.     if (!exiting)
  311.         pc = *((Inst **)(savepc + 2)); /* next statement */
  312. }
  313.  
  314. void tofile ()
  315. {
  316.     Datum    d;
  317.  
  318.     d = pop ();
  319.     PP_TRACE (("tofile %s", d.str));
  320.     switch (putfile (d.str)) {
  321.         case RP_OK:
  322.         d.str = true;
  323.         break;
  324.         case RP_AGN:
  325.         d.str = rp_agn;
  326.         break;
  327.         default:
  328.         case RP_BAD:
  329.         d.str = false;
  330.         break;
  331.     }
  332.     push (d);
  333. }
  334.  
  335. void tounixfile ()
  336. {
  337.     Datum    d;
  338.  
  339.     d = pop ();
  340.     PP_TRACE (("tounixfile %s", d.str));
  341.     switch (putunixfile (d.str)) {
  342.         case RP_OK:
  343.         d.str = true;
  344.         break;
  345.         case RP_AGN:
  346.         d.str = rp_agn;
  347.         break;
  348.         default:
  349.         case RP_BAD:
  350.         d.str = false;
  351.         break;
  352.     }
  353.     push (d);
  354. }
  355.  
  356. void topipe ()
  357. {
  358.     Datum d;
  359.  
  360.     d = pop ();
  361.     PP_TRACE (("topipe %s", d.str));
  362.     switch (putpipe (d.str)) {
  363.         case RP_OK:
  364.         d.str = true;
  365.         break;
  366.         case RP_BAD:
  367.         d.str = false;
  368.         break;
  369.         default:
  370.         case RP_AGN:
  371.         d.str = rp_agn;
  372.         break;
  373.     }
  374.     PP_TRACE (("topipe = %s", d.str));
  375.     push (d);
  376. }
  377.  
  378. void    setdeliver ()
  379. {
  380.     Datum    d;
  381.     Symbol    *sym;
  382.  
  383.     d = pop ();
  384.     PP_TRACE (("setdelivered %s", d.str));
  385.     sym = lookup (delivered);
  386.     if (sym == NULL)
  387.         adios (NULLCP, "symbol %s not defined!!", delivered);
  388.     sym -> str = d.str;
  389.     if (lexequ (d.str, rp_agn) == 0)
  390.         exiting = 1;
  391.     push (d);
  392. }
  393.  
  394. void exitproc ()
  395. {
  396.     Datum d;
  397.     Symbol    *sym;
  398.  
  399.     d = pop ();
  400.     PP_TRACE (("exitproc %s", d.str));
  401.     sym = lookup (delivered);
  402.     if (sym == NULL)
  403.         adios (NULLCP, "symbol %s not defined!!", delivered);
  404.     sym -> str = d.str;
  405.     exiting = 1;
  406. }
  407.  
  408. void    defexitproc ()
  409. {
  410.     Symbol    *sym;
  411.     Datum d;
  412.  
  413.     PP_TRACE (("defexitproc"));
  414.     sym = lookup (delivered);
  415.     if (sym == NULL)
  416.         adios (NULLCP, "symbol %s not defined!!", delivered);
  417.     d.str = sym -> str;
  418.     push (d);
  419.     exiting = 1;
  420. }
  421.  
  422. void    prexpr ()
  423. {
  424.     Datum    d;
  425.  
  426.     d = pop ();
  427.     printit (d.str);
  428. }
  429.  
  430. void assign ()
  431. {
  432.     Datum    d1, d2;
  433.  
  434.     d1 = pop ();
  435.     d2 = pop ();
  436.     if (d1.sym -> type != strvar)
  437.         adios (NULLCP, "assignment to non-variable '%s'",
  438.                d1.sym -> name);
  439.     PP_TRACE (("%s = %s", d1.sym -> name, d2.str));
  440.     d1.sym -> str = d2.str;
  441.     push (d2);
  442. }
  443.  
  444. checkmacro (s)
  445. char    *s;
  446. {
  447.     char    *p, *q;
  448.  
  449.     for (q = s; p = index(q, '$'); q = p + 1) {
  450.         if (p[1] == '(') {
  451.             char *cp, buf[1024];
  452.  
  453.             for (p += 2, cp = buf; *p; p++)
  454.                 if (*p == ')')
  455.                     break;
  456.                 else *cp ++ = *p;
  457.             *cp = 0;
  458.             if (lookup (buf) == (Symbol *)0)
  459.                 install (strdup (buf), field);
  460.         }
  461.     }
  462. }
  463.  
  464. static Symbol *symlist;
  465.  
  466.  
  467. Symbol    *lookup (s)
  468. char    *s;
  469. {
  470.     Symbol    *sp;
  471.  
  472.     for (sp = symlist; sp; sp = sp -> next)
  473.         if (strcmp (sp -> name, s) == 0)
  474.             return sp;
  475.     return 0;
  476. }
  477.  
  478.  
  479. Symbol    *install (str, t)
  480. char    *str;
  481. stype    t;
  482. {
  483.     Symbol *sp;
  484.  
  485.     PP_TRACE (("Install %s",str));
  486.     sp = (Symbol *) smalloc (sizeof *sp);
  487.     sp -> name = str;
  488.     sp -> type = t;
  489.     sp -> str = false;
  490.  
  491.     sp -> next = symlist;
  492.     symlist = sp;
  493.     return sp;
  494. }
  495.  
  496. reset_syms ()
  497. {
  498.     Symbol **spp, *sp;
  499.  
  500.     PP_TRACE (("reset symbols"));
  501.     for (spp = &symlist; *spp; ) {    /* half hearted free attempt */
  502.         sp = *spp;
  503.         spp = &(*spp) -> next;
  504.         if (sp -> name && *sp -> name)
  505.             free (sp -> name);
  506.         free ((char *)sp);
  507.     }
  508.     symlist = 0;
  509. }
  510.  
  511. int yywrap ()
  512. {
  513.     return 1;
  514. }
  515.  
  516. yyerror (s)
  517. char    *s;
  518. {
  519.     extern char yytext[];
  520.  
  521.     adios (NULLCP, "%s near line %d (last token was '%s')",
  522.            s, lineno, yytext);
  523. }
  524.  
  525. fillin_var (str, dest)
  526. char    *str;
  527. char    dest[];
  528. {
  529.     Symbol *sp;
  530.  
  531.     if (sp = lookup (str))
  532.         (void) sprintf (dest, "PATH=%s", sp -> str);
  533. }
  534.  
  535. install_vars (vars, n, maxv)
  536. Expand vars[];
  537. int    n;
  538. int    maxv;
  539. {
  540.     int i;
  541.     Symbol *sp;
  542.  
  543.     for (i = n, sp = symlist; i < maxv && sp;
  544.          sp = sp -> next) {
  545.         if (sp -> type == field)
  546.             continue;
  547.         vars[i].macro = strdup (sp -> name);
  548.         vars[i].expansion = strdup (sp -> str);
  549.         i++;
  550.     }
  551.     vars[i].macro = vars[i].expansion = NULLCP;
  552.  
  553. }
  554.  
  555. void create_var (var)
  556. Expand *var;
  557. {
  558.     Symbol *sp;
  559.  
  560.     if ((sp = lookup (var -> macro)) == NULL)
  561.         sp = install (var -> macro, field);
  562.     sp -> str = var -> expansion;
  563. }
  564.